package com.yanqu.road.server.manager.activity.carptrip;

import com.yanqu.road.dao.impl.activity.carptrip.CarpTripConfigDaoImpl;
import com.yanqu.road.dao.impl.activity.carptrip.CarpTripDrawNoticeDataDaoImpl;
import com.yanqu.road.dao.impl.activity.carptrip.CarpTripPvPCellDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.carptrip.config.CarpTripPvpTopInfo;
import com.yanqu.road.entity.activity.carptrip.data.CarpTripDrawNoticeData;
import com.yanqu.road.entity.activity.carptrip.data.CarpTripPvPCellData;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.CarpTripProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.List;

public class CarpTripActivity {

    private ActivityInfo activityInfo;

    private List<CarpTripDrawNoticeData> noticeDataList;

    //配置
    private List<CarpTripPvpTopInfo> pvpTopInfoList;

    //pvp数据
    private List<CarpTripPvPCellData> pvPCellDataList;

    public CarpTripActivity(ActivityInfo activityInfo) {
        this.activityInfo = activityInfo;
    }

    public void init() {
        pvpTopInfoList = new CarpTripConfigDaoImpl().getCarpTripPvpTopInfoList(activityInfo.getActivityId());
        noticeDataList = new CarpTripDrawNoticeDataDaoImpl().getCarpTripDrawNoticeData(activityInfo.getActivityId(), 50);
        pvPCellDataList = new CarpTripPvPCellDataDaoImpl().getCarpTripPvPCellData(activityInfo.getActivityId());

        for (CarpTripPvpTopInfo topInfo : pvpTopInfoList) {
            CarpTripPvPCellData data = getCarpTripPvPCellData(topInfo.getCellNum());
            if(data == null){
                data = initPvpCellData(topInfo);
                pvPCellDataList.add(data);
            }
        }
    }

    private CarpTripPvPCellData initPvpCellData(CarpTripPvpTopInfo topInfo) {
        CarpTripPvPCellData data = new CarpTripPvPCellData();
        data.setActivityId(activityInfo.getActivityId());
        data.setCellId(topInfo.getCellNum());
        data.setBlood(topInfo.getAbility());
        data.setUserId(topInfo.getPic());
        data.setInsertOption();
        return data;
    }

    /**
     * pvp
     */
    public synchronized void fight(long serverId, long userId, int cellId, long targetId, String myAbility, UserBaseInfo myBaseInfo) {

        //目标位置是否变更
        CarpTripPvPCellData targetCellData = getCarpTripPvPCellData(cellId);
        if(targetCellData == null){
            sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_LOCK);
            return;
        }
        if(targetCellData.getUserId() != targetId){
            sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_TARGET_CHANGE);
            return;
        }

        //挑战非首层，必须在底下一层
        if(cellId > 1){
            CarpTripPvPCellData myCell = getCarpTripPvPCellData(cellId - 1);
            if(myCell == null){
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_LOCK);
                return;
            }
            if(myCell.getUserId() != userId){
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_SELF_CHANGE);
                return;
            }
        }

        UserBaseInfo targetBaseInfo = targetCellData.getUserBaseInfo();
        long targetUserId = targetCellData.getUserId();
        String targetAbility = targetCellData.getBlood();

        //战斗返回，或者日志
        CarpTripProto.CarpTripPVPFightRespMsg.Builder respMsg = CarpTripProto.CarpTripPVPFightRespMsg.newBuilder();

        //我的位置
        CarpTripPvPCellData cellData = getCarpTripPvPCellDataByUserId(userId);
        if(cellData == null){
            if(cellId != 1) {
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_SELF_CHANGE);
                return;
            }
            //实力不足
            if(new BigInteger(myAbility).compareTo(new BigInteger(targetCellData.getBlood())) < 0){
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_ABILITY_FAILS);
                return;
            }
            //不在榜上
            targetCellData.setUserId(userId);
            targetCellData.setUserBaseInfo(myBaseInfo);
            targetCellData.setBlood(myAbility);

        }else {
            if(cellId != cellData.getCellId() + 1){
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_SELF_CHANGE);
                return;
            }
            //实力不足
            if(new BigInteger(myAbility).compareTo(new BigInteger(targetCellData.getBlood())) < 0){
                sendFightResultError(userId, serverId, GameErrorCode.E_CARP_TRIP_TOP_CELL_ABILITY_FAILS);
                return;
            }
            //在榜上,交换位置
            if(targetId > 10000) {
                cellData.setUserId(targetCellData.getUserId());
                cellData.setBlood(targetCellData.getBlood());
                cellData.setUserBaseInfo(targetCellData.getUserBaseInfo());
            }else {
                //回填npc
                CarpTripPvpTopInfo npc = getCarpTripPvpTopInfo(cellData.getCellId());
                cellData.setUserBaseInfo(null);
                cellData.setUserId(cellData.getCellId());
                cellData.setBlood(npc.getAbility());
            }
            targetCellData.setUserId(userId);
            targetCellData.setUserBaseInfo(myBaseInfo);
            targetCellData.setBlood(myAbility);
        }

        //非npc
        if(targetId > 10000) {
            //通知对手（战报）
            CarpTripProto.CarpTripPVPReportTemp.Builder reportMsg = CarpTripProto.CarpTripPVPReportTemp.newBuilder();
            reportMsg.setEnemyId(userId);
            reportMsg.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(myBaseInfo));
            reportMsg.setAbility(myAbility);
            reportMsg.setTime(System.currentTimeMillis());
            reportMsg.setMyAbility(targetAbility);
            reportMsg.setOldCellId(cellId);
            reportMsg.setNewCellId(cellId - 1);
            MessageHelper.sendPacket(targetBaseInfo.getServerId(), targetId, YanQuMessageUtils.buildMessage(Protocol.S_CARP_TRIP_PVP_FIGHT_REPORT_FROM_CROSS, reportMsg));
        }

        respMsg.setNewCellId(cellId);
        respMsg.setRet(0);
        respMsg.setEnemyUserId(targetUserId);
        respMsg.setEnemyAbility(targetAbility);
        if(targetBaseInfo != null){
            respMsg.setEnemy(PlayerBasePb.parsePlayerBaseTempMsg(targetBaseInfo));
        }
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            CarpTripProto.CarpTripPVPCellDataTemp.Builder builder = parsePVPCellDataBuilder(data);
            respMsg.addPvp(builder);
        }
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.S_CARP_TRIP_PVP_FIGHT_FROM_CROSS, respMsg));

        //
        syncPVPData(serverId, userId);
    }

    public synchronized void updateAbility(long userId, String ability){
        if(StringUtils.isNullOrEmpty(ability)){
            return;
        }
        BigInteger val = new BigInteger(ability);
        if(val.compareTo(BigInteger.ZERO) <= 0){
            return;
        }
        for (CarpTripPvPCellData data : pvPCellDataList) {
            if(data.getUserId() == userId){
                data.setBlood(ability);
                CrossCarpTripActivityMgr.getLogger().info("userId {} update ability {}", userId, ability);
                break;
            }
        }
    }

    public void sendFightResultError(long userId, long serverId, int ret){
        CarpTripProto.CarpTripPVPFightRespMsg.Builder respMsg = CarpTripProto.CarpTripPVPFightRespMsg.newBuilder();
        respMsg.setRet(ret);
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            CarpTripProto.CarpTripPVPCellDataTemp.Builder builder = parsePVPCellDataBuilder(data);
            respMsg.addPvp(builder);
        }
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.U_CARP_TRIP_PVP_FIGHT, respMsg));
    }

    private CarpTripProto.CarpTripPVPCellDataTemp.Builder parsePVPCellDataBuilder(CarpTripPvPCellData data) {
        CarpTripProto.CarpTripPVPCellDataTemp.Builder builder = CarpTripProto.CarpTripPVPCellDataTemp.newBuilder();
        builder.setBlood(data.getBlood());
        builder.setUserId(data.getUserId());
        builder.setCellId(data.getCellId());
        if(data.getUserId() < 10000){
            builder.setNpcId((int)data.getUserId());
        }else {
            builder.setNpcId(0);
        }
        if(data.getUserBaseInfo() != null){
            builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(data.getUserBaseInfo()));
        }
        return builder;
    }

    public void syncPVPData(long serverId, long userId) {
        CarpTripProto.CarpTripPVPCellDataSyncMsg.Builder respMsg = CarpTripProto.CarpTripPVPCellDataSyncMsg.newBuilder();
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            CarpTripProto.CarpTripPVPCellDataTemp.Builder builder = parsePVPCellDataBuilder(data);
            respMsg.addPvp(builder);
        }
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.U_CARP_TRIP_SYNC_PVP_DATA, respMsg));
    }

    public void getPVPData(long serverId, long userId) {
        CarpTripProto.GetCarpTripPVPCellDataRspMsg.Builder respMsg = CarpTripProto.GetCarpTripPVPCellDataRspMsg.newBuilder();
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            CarpTripProto.CarpTripPVPCellDataTemp.Builder builder = parsePVPCellDataBuilder(data);
            respMsg.addPvp(builder);
        }
        respMsg.setRet(0);
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.U_CARP_TRIP_GET_PVP_DATA, respMsg));
    }

    public void save() {
        for (int i = 0; i < noticeDataList.size(); i++) {
            CarpTripDrawNoticeData noticeData = noticeDataList.get(i);
            if(noticeData.isInsertOption()){
                new CarpTripDrawNoticeDataDaoImpl().add(noticeData);
            }else if(noticeData.isUpdateOption()){
                new CarpTripDrawNoticeDataDaoImpl().update(noticeData);
            }
        }

        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            if(data.isInsertOption()){
                new CarpTripPvPCellDataDaoImpl().add(data);
            }else if(data.isUpdateOption()){
                new CarpTripPvPCellDataDaoImpl().update(data);
            }
        }
    }

    public CarpTripPvPCellData getCarpTripPvPCellData(int cellId){
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            if(data.getCellId() == cellId){
                return data;
            }
        }
        return null;
    }

    public CarpTripPvPCellData getCarpTripPvPCellDataByUserId(long userId){
        for (int i = 0; i < pvPCellDataList.size(); i++) {
            CarpTripPvPCellData data = pvPCellDataList.get(i);
            if(data.getUserId() == userId){
                return data;
            }
        }
        return null;
    }

    public CarpTripPvpTopInfo getCarpTripPvpTopInfo(int cellId){
        for (CarpTripPvpTopInfo pvpTopInfo : pvpTopInfoList) {
            if(pvpTopInfo.getCellNum() == cellId){
                return pvpTopInfo;
            }
        }
        return null;
    }

    public ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public void setActivityInfo(ActivityInfo activityInfo) {
        this.activityInfo = activityInfo;
    }

    public List<CarpTripDrawNoticeData> getNoticeDataList() {
        return noticeDataList;
    }

    public void setNoticeDataList(List<CarpTripDrawNoticeData> noticeDataList) {
        this.noticeDataList = noticeDataList;
    }

    public List<CarpTripPvpTopInfo> getPvpTopInfoList() {
        return pvpTopInfoList;
    }

    public void setPvpTopInfoList(List<CarpTripPvpTopInfo> pvpTopInfoList) {
        this.pvpTopInfoList = pvpTopInfoList;
    }

    public List<CarpTripPvPCellData> getPvPCellDataList() {
        return pvPCellDataList;
    }

    public void setPvPCellDataList(List<CarpTripPvPCellData> pvPCellDataList) {
        this.pvPCellDataList = pvPCellDataList;
    }

    public void addDrawNotice(long serverId, long playerId, List<CarpTripProto.CarpTripNoticeMsg> noticeList) {
        synchronized (noticeDataList){
            for (CarpTripProto.CarpTripNoticeMsg noticeMsg : noticeList) {
                CarpTripDrawNoticeData noticeData = new CarpTripDrawNoticeData();
                noticeData.setActivityId(activityInfo.getActivityId());
                noticeData.setGetTime(noticeMsg.getTime());
                noticeData.setServerId(serverId);
                noticeData.setUserId(playerId);
                noticeData.setNickName(noticeMsg.getNickName());
                noticeData.setReward(noticeMsg.getReward());
                noticeData.setParam(noticeMsg.getValue() + "");
                noticeData.setInsertOption();
                noticeDataList.add(noticeData);
            }
            while (noticeDataList.size() > 50){
                noticeDataList.remove(0);
            }
        }
    }

    public CarpTripProto.CarpTripNoticeRespMsg.Builder getNoticeList() {

        CarpTripProto.CarpTripNoticeRespMsg.Builder respMsg = CarpTripProto.CarpTripNoticeRespMsg.newBuilder();

        List<CarpTripDrawNoticeData> list = noticeDataList;
        if(list != null){
            for (int i = 0; i < list.size(); i++) {
                CarpTripProto.CarpTripNoticeMsg.Builder builder = CarpTripProto.CarpTripNoticeMsg.newBuilder();
                CarpTripDrawNoticeData noticeData = list.get(i);
                builder.setTime(noticeData.getGetTime());
                builder.setReward(noticeData.getReward());
                builder.setServerId(noticeData.getServerId());
                builder.setNickName(noticeData.getNickName());
                builder.setValue(Integer.valueOf(noticeData.getParam()));
                respMsg.addNoticeList(builder);
            }
        }
        respMsg.setRet(0);
        return respMsg;
    }
}
